package com.tanhua.dubbo.api;

import cn.hutool.system.UserInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.dubbo.mappers.MeasuringSoulMapper;
import com.tanhua.dubbo.mappers.ReportMapper;
import com.tanhua.model.domain.Exam;
import com.tanhua.model.domain.Options;
import com.tanhua.model.domain.Report;
import com.tanhua.model.dto.AnswerDTO;
import com.tanhua.model.dto.ExamDTO;
import com.tanhua.model.vo.ExamVO;
import com.tanhua.model.vo.QuestionsVO;
import com.tanhua.model.vo.ReportVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 *
 */
@DubboService
public class MeasuringSoulApiImpl implements MeasuringSoulApi {

    @Autowired
    private MeasuringSoulMapper soulMapper;
    /**
     * 查询该用户能看到的试卷列表
     * @param userId
     * @return
     */
    @Override
    public List<ExamVO> selectExamWithUser(Long userId) {
        //查询用户的试卷列表
        List<ExamDTO> examDTOList = soulMapper.selectExamReportByUserId(userId);
        //处理试卷封装ExamVO
        List<ExamVO> examVOS = expactExamVO(examDTOList);
        //遍历VO,为vo封装questions和options
        if(examVOS.size() > 0){
            //依次查询其试题和试题选项数据并封装
            for (ExamVO vo : examVOS) {
                Long examId = Long.valueOf(vo.getId());
                String level = vo.getLevel();
                List<QuestionsVO> questionsVOList = soulMapper.selectQuestionsAndOptionsByExamId(examId,level);
                vo.setQuestions(questionsVOList);
            }
        }
        return examVOS;
    }


    /**
     * 封装VO，并设置vo的isLock属性！
     * @param examDTOList
     * @return
     */
    private List<ExamVO> expactExamVO(List<ExamDTO> examDTOList){
        Iterator<ExamDTO> iterator = examDTOList.iterator();
        List<ExamVO> vos = new ArrayList<>();
        if(iterator.hasNext()){
            //先收集第一条，并得到第一条的reportId,查看是否为空。
            ExamDTO firstExamDTO = iterator.next();
            ExamVO vo = ExamVO.setExamVOData(firstExamDTO);
            vo.setIsLock(0);
            vos.add(vo);
            //递归处理其他数据
            setLock(firstExamDTO.getReportId() == null,iterator,vos);
        }
        return vos;
    }

    //为null true 则下面的都锁定
    //不为null false 则下面的继续迭代
    //vo是下一条
    /**
     * @param preReportIdIsNull  上一个报告ID是否为null
     * @param examDTOIterator 数据库中的试卷DTO迭代器
     * @param vos 要封装的VO集合
     */
    private void setLock(boolean preReportIdIsNull,Iterator<ExamDTO> examDTOIterator,List<ExamVO> vos){
        //如果没有数据了则终止迭代
        if(!examDTOIterator.hasNext()) return;
        //如果还有DTO则继续处理
        ExamDTO examDTO = examDTOIterator.next();
        ExamVO vo = ExamVO.setExamVOData(examDTO);
        //判断上一个试卷如果有报告ID，则说明其已经回答过了，则下一个需要开放
        if(preReportIdIsNull)
            vo.setIsLock(1);
        else
            vo.setIsLock(0);

        vos.add(vo);
        setLock(examDTO.getReportId() == null,examDTOIterator,vos);
    }

    /**
     * <p>保存用户答题记录</p>
     * <p>计算得分并保存用户答卷记录</p>
     * <p>根据得分查询其报告ID</p>
     * @param answers
     * @param userId
     * @return
     */
    @Override
    public String saveAnswerAndReport(List<AnswerDTO> answers, Long userId) {
        //查询对应的exam记录
        if(answers != null && answers.size() > 0){
            String questionId = answers.get(0).getQuestionId();
            Exam exam = soulMapper.selectExamByQuestionsLevel(questionId);

            //统计总分的变量
            int totalScore = 0;
            for (AnswerDTO answer : answers) {
//                String questionId = answer.getQuestionId();
                //根据问题的level得到对应的试卷 -- 此处的设定与我自己设定的需求相符合

                String optionId = answer.getOptionId();
                //根据选项ID计算用户回答该试题的分数
                Options options = soulMapper.selectOptionsById(Long.valueOf(optionId));
                Integer optionsScore = options.getScore();
                totalScore += optionsScore;
            }
            //根据totalScore查询对应的报告ID
            Report report = soulMapper.selectReportByScore(totalScore);
            if(report != null){
                Long reportId = report.getId();
                //保存用户与试卷、报告的关系
                Map<String,Object> userExam = new HashMap<>();
                userExam.put("userId",userId);
                userExam.put("level",exam.getLevel());
                userExam.put("examId",exam.getId());
                userExam.put("reportId",reportId);
                userExam.put("created",new Date());
                soulMapper.saveExamRelReport(userExam);
                return report.getId().toString();
            }else
                throw new RuntimeException("报告生成失败");
        }else{
            throw new RuntimeException("未提交答案");
        }
    }

    @Autowired
    private ReportMapper reportMapper;
    /**
     * 查询报告详情
     * 查询与用户类似性格的人
     * @param id
     * @param userId
     * @return
     */
    @Override
    public ReportVO selectReportById(Integer id, Long userId) {
        //
        Report report = reportMapper.selectById(id);
        ReportVO vo = new ReportVO();
        vo.setConclusion(report.getConclusion());
        vo.setCover(report.getCover());
        String dimensions = report.getDimensions();
        List<Map> dimensionsList = null;
        try {
            dimensionsList = new ObjectMapper().readValue(dimensions, new TypeReference<List<Map>>(){});
            vo.setDimensions(dimensionsList);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //查询关联用户 —— 即，相同reportId的用户
        List<UserInfo> userInfoList = soulMapper.selectUserInfoByReportId(id);
        //此处应该排除自己,偷懒不做了
        vo.setSimilarYou(userInfoList);
        return vo;
    }
}
